#include <avr/io.h>
#include <avr/interrupt.h>
#include "Cspi.h"

static CSpi* spi;

// SPI interrupt service handler
SIGNAL(SIG_SPI)
{
  spi->TransferComplete = TRUE;
}

// access routines
CSpi::CSpi(void) {
  sbi(PORTB, 1); // set SCK hi
  sbi(DDRB, 1); // set SCK as output
  cbi(DDRB, 3); // set MISO as input
  sbi(DDRB, 2); // set MOSI as output
  sbi(DDRB, 0); // SS must be output for Master mode to work

  // setup SPI interface :
  // master mode
  sbi(SPCR, MSTR);
  // clock = f/64
  cbi(SPCR, SPR0);
  sbi(SPCR, SPR1);
  // select clock phase positive-going in middle of data
  cbi(SPCR, CPOL);
  // Data order MSB first
  cbi(SPCR,DORD);
  // enable SPI
  sbi(SPCR, SPE);
  // clear status
  inb(SPSR);
  TransferComplete = TRUE;
  // enable SPI interrupt
  sbi(SPCR, SPIE);
  spi = this;

}

void CSpi::sendbyte(u08 data) {
  // send a byte over SPI and ignore reply
  while (!TransferComplete)
    ;
  TransferComplete = FALSE;
  SPDR = data;
}

void CSpi::sendBlock(u08* data, u08 len) {
  u08 i;
  for (i = 0; i < len; i++) {
    this->sendbyte(data[i]);
  }
}

void CSpi::transferBlock(u08* data, u08* buffer, u08 len) {
  u08 i;
  for (i = 0; i < len; i++) {
    buffer[i] = this->transferbyte(data[i]);
  }
}

u08 CSpi::transferbyte(u08 data) {
  // send the given data
  TransferComplete = FALSE;
  SPDR = data;
  // wait for transfer to complete
  while (!TransferComplete)
    ;
  // return the received data
  return (SPDR);
}
